Skip to content

fix(idl): avoid quoted string constant values#4580

Closed
abhinavgautam01 wants to merge 3 commits into
otter-sec:masterfrom
abhinavgautam01:fix/3607-constant-string-ts-quotes
Closed

fix(idl): avoid quoted string constant values#4580
abhinavgautam01 wants to merge 3 commits into
otter-sec:masterfrom
abhinavgautam01:fix/3607-constant-string-ts-quotes

Conversation

@abhinavgautam01
Copy link
Copy Markdown
Contributor

Fixes #3607

Summary

  • Emit string #[constant] values using their actual string contents instead of Rust debug formatting
  • Prevent generated IDL / TypeScript types from containing escaped quote wrappers like "\"favor\""
  • Add regression coverage for a &str constant in the IDL fixture

Testing

  • cargo test -p anchor-syn
  • cargo test -p anchor-cli idl_ts_preserves_literal_values
  • CARGO_NET_OFFLINE=true target/debug/anchor idl build -o /private/tmp/idl-3607.json
  • diff -u tests/idl/idls/idl.json /private/tmp/idl-3607.json
  • target/debug/anchor idl type /private/tmp/idl-3607.json > /private/tmp/idl-3607.ts
  • rg -n 'seedPrefix|favor|\\"favor\\"' /private/tmp/idl-3607.ts
  • git diff --check

Copy link
Copy Markdown
Collaborator

@0x4ka5h 0x4ka5h left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@0x4ka5h 0x4ka5h requested a review from jamie-osec May 25, 2026 11:04
Comment thread tests/events/tests/events.ts Outdated
@jamie-osec
Copy link
Copy Markdown
Collaborator

I'm not sure if this is workable, at least in v1, as this would be a breaking change to IDL consumers. For example, declare_program parses the value as a Rust expression and emits it directly:

let val = syn::parse_str::<syn::Expr>(&c.value)
.unwrap()
.to_token_stream();
let val = match &c.ty {
IdlType::Bytes => quote! { &#val },
IdlType::Pubkey => quote!(Pubkey::from_str_const(stringify!(#val))),
_ => val,
};
quote! {
#docs
pub const #name: #ty = #val;
}

So this causes declare program to emit const MY_CONSTANT: &str = value, which would fail to compile with identifer value not found.

@abhinavgautam01 abhinavgautam01 force-pushed the fix/3607-constant-string-ts-quotes branch from 23fa1c3 to 033514d Compare May 26, 2026 13:12
@abhinavgautam01
Copy link
Copy Markdown
Contributor Author

I'm not sure if this is workable, at least in v1, as this would be a breaking change to IDL consumers. For example, declare_program parses the value as a Rust expression and emits it directly:

let val = syn::parse_str::<syn::Expr>(&c.value)
.unwrap()
.to_token_stream();
let val = match &c.ty {
IdlType::Bytes => quote! { &#val },
IdlType::Pubkey => quote!(Pubkey::from_str_const(stringify!(#val))),
_ => val,
};
quote! {
#docs
pub const #name: #ty = #val;
}

So this causes declare program to emit const MY_CONSTANT: &str = value, which would fail to compile with identifer value not found.

i updated the approach so the JSON IDL still keeps string constant values as Rust expressions, preserving compatibility with declare_program and other IDL consumers....

the change is now limited to the generated TypeScript type helper, where string literal constants are normalized for target/types/*.ts only...

@jamie-osec
Copy link
Copy Markdown
Collaborator

What exactly are the new changes doing?

@abhinavgautam01 abhinavgautam01 force-pushed the fix/3607-constant-string-ts-quotes branch from 033514d to d0bcada Compare May 26, 2026 13:39
@abhinavgautam01
Copy link
Copy Markdown
Contributor Author

What exactly are the new changes doing?

the new changes keep the actual JSON IDL unchanged for compatibility: string constants are still stored as Rust expressions, e.g. "\"favor\"", so declare_program and other Rust-side IDL consumers continue to work...

the only behavior change is in the generated TypeScript type helper (target/types/*.ts). before rendering that TS type, string constant values that are valid JSON string literals are decoded once, so "\"favor\"" is shown as "favor" in the generated TS helper. Non-literal values like SEED_PREFIX are left unchanged...

@jamie-osec
Copy link
Copy Markdown
Collaborator

Can you add a test for the real behavioral change, and update the PR title/description to reflect it?

@jamie-osec
Copy link
Copy Markdown
Collaborator

Actually sorry, I'm going to close this based on the reasoning in the linked issue. I don't think this break is worth it.

@jamie-osec jamie-osec closed this May 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

#[constant] &str in generated types/xxx.ts has \" prefix and suffix

3 participants